/*
Javier Kohen's Java Framework Classes.
Copyright (C) 2000-2001  Javier Kohen <jkohen at tough.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package ar.com.jkohen.util;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.net.URL;
import java.util.*;
import java.io.*;


public class Resources extends Observable implements Runnable
{
	private static Object obj;
	private static Class classloader;
	private static MediaTracker tracker;
	private static Thread loader;
	private static String path;
	private static Vector files;

	public static Properties lang_resource;
	public static Properties img_resource;
	public static String help_resource;


	// Events sounds.

	public static final int SND_ON = 0;
	public static final int SND_OFFAWAY = 1;
	public static final int SND_OFF = 2;

	public final static int EVENT_JOIN = 0;
	public final static int EVENT_PART = 1;
	public final static int EVENT_OP = 2;
	public final static int EVENT_DEOP = 3;
	public final static int EVENT_KICK = 4;
	public final static int EVENT_BAN = 5;
	public final static int EVENT_QUIT = 6;
	public final static int EVENT_PRVMSG = 7;
	public final static int EVENT_MSG = 8;

	public final static int EVENTS = 9;

	public static Hashtable SOUNDS = new Hashtable();

	// Images buttons.

	public static Image LARGE_NORMAL;
    public static Image LARGE_PRESSED;
	public static Image LARGE_DISABLED;
	public static Image LARGE_ALERT;
	public static Image LARGE_WAIT;

	public static Image SMALL_NORMAL;
    public static Image SMALL_PRESSED;
    public static Image SMALL_DISABLED;

	public Resources(Object target, String pref_lang)
	{
		this.obj = target;
		this.classloader = (target instanceof Class) ? (Class)target : target.getClass();
		this.tracker = new MediaTracker((Component)target);


		/*
		** By default, this will load the English language files
		** Then, this will try to load JVM's default locale ones.
		** So, you should always include *_en.properties files.
		*/

		try
		{
			Locale en_locale = new Locale("en", "");
			Properties en_lang_resource = null;
			Properties en_img_resource = null;
			String en_help_resource = null;
			try
			{
				en_lang_resource = getBundle("eirc", en_locale, null);
				en_img_resource = getBundle("images", en_locale, null);
				en_help_resource = getBundle("help", en_locale);
			}
			catch (MissingResourceException ex) { System.err.println("Cannot load " + ex.getKey()); }

			Locale locale = null;
			if (pref_lang != null && pref_lang.length() == 2)
				locale = new Locale(pref_lang, "");
			else
				locale = Locale.getDefault();

			lang_resource = getBundle("eirc", locale, en_lang_resource);
			img_resource = getBundle("images", locale, en_img_resource);
			help_resource = getBundle("help", locale);
		}
		catch (MissingResourceException ex) { System.err.println("Cannot load " + ex.getKey()); }

		cacheImages();
	}

	private static void cacheImages()
	{
		LARGE_NORMAL = getImage("button.large.normal");
		LARGE_PRESSED = getImage("button.large.pressed");
		LARGE_DISABLED = getImage("button.large.disabled");
		LARGE_ALERT = getImage("button.large.alert");
		LARGE_WAIT = getImage("button.large.wait");

		SMALL_NORMAL = getImage("button.small.normal");
		SMALL_PRESSED = getImage("button.small.pressed");
		SMALL_DISABLED = getImage("button.small.disabled");

	}

	public void cacheSounds(Vector files, String path)
	{
		this.files = files;
		this.path = path;
		start();
	}

	public void start()
	{
		if (loader == null)
		{
        	loader = new Thread(this, "sound_loader");
			loader.start();
		}
	}

	public void run()
	{
		int i = 1;
		Enumeration e = files.elements();
		while (e.hasMoreElements() && loader == Thread.currentThread())
		{
   			String key = (String)e.nextElement();
			AudioClip au = createSound(path + "/" + key);
			if (au != null)
			{
	   			SOUNDS.put(key, au);

				setChanged();
				notifyObservers(key);
			}

            try
			{
				Thread.sleep(500);
            }
			catch (InterruptedException ex) {}
   	    }
		stop();
	}

	public void stop()
	{
		loader = null;
	}

    public static Image getImage(String key)
    {
    	String name = getLabel(key);
    	if (name != null && !name.equals(""))
		{
			try
			{
				Image img = createImage(name);
				tracker.addImage(img, 0);
				tracker.waitForID(0, 1000);
		    	return(img);
			} catch (InterruptedException e) {}
		}
    	return(null);
    }

    public static String getLabel(String key)
    {
    	String value = img_resource.getProperty(key);
	    if (value == null)
	    	System.out.println("Missing key : " + key);

	    return(value);
    }

    public static String getString(String key)
    {
    	String value = lang_resource.getProperty(key);
	    if (value == null)
	    	System.out.println("Missing key : " + key);

	    return(value);
    }

	public static String getHelp()
    {
	    return(help_resource);
    }

	private Properties getBundle(String name, Locale loc, Properties defaults) throws MissingResourceException
	{
		Properties pr = null;
		if (defaults != null)
			 pr = new Properties(defaults);
		else
			pr = new Properties();
		String resource_name = name + "_" + loc.getLanguage() + ".properties";

		try
		{
    		InputStream in = classloader.getResourceAsStream(resource_name);
			if (in != null)
			{
				pr.load(in);
				in.close();
			}
			if (pr == null)
			{
				throw new MissingResourceException("Cannot load properties file" , "Resource", resource_name);
			}
		}
		catch (IOException e)
		{
			throw new MissingResourceException("Cannot load properties file" , "Resource", resource_name);
		}

		return(pr);
	}
	
	private String getBundle(String name, Locale loc) throws MissingResourceException
	{
		String txt = new String();
		String resource_name = name + "_" + loc.getLanguage() + ".txt";

		try
		{
			InputStream is = classloader.getResourceAsStream(resource_name);
			if (is == null)
				throw new MissingResourceException("Cannot load text file" , "Resource", resource_name);

    		BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF8"));
			String s;
            while((s = br.readLine()) != null)
            {
				if (s.equals(""))
					s = "\r";
					
            	txt += s + "\n";
            }

            br.close();
		}
		catch (IOException e)
		{
			throw new MissingResourceException("Cannot load text file" , "Resource", resource_name);
		}

		return(txt);
	}

    /**
     * BUGS:
     *  * Netscape Navigator (tested with 4.7x) won't load files from outside a JAR.
     *  * Life would be easier if Netscape Navigator supported Class.getResource().
	 *	* Their not supporting it is actually documented on Netscape's Developers website.
     */
/*
    public static byte [] getResource(String name, Object target) throws IOException
	{
    	// Resolve object to a Class, if needed.
	   	Class cl = (target instanceof Class) ? (Class)target : target.getClass();

    	InputStream is = cl.getResourceAsStream(name);
    	BufferedInputStream bis = new BufferedInputStream(is);
    	ByteArrayOutputStream baos = new ByteArrayOutputStream();

    	try
    	{
        	int pos = 0;
        	int readed;
        	final int chunk_size = 4096;
          	byte [] buf = new byte [chunk_size];

        	while ((readed = bis.read(buf, 0, chunk_size)) != -1)
    		{
        	    baos.write(buf, pos, readed);
        	    pos += readed;
        	}

        	return baos.toByteArray();
        }
        catch (Exception e)
        {
        	throw new IOException("Cannot open image file " + name);
        }
    }
*/
    private static Image createImage(String resource_name)
	{
/*
		try
		{
			byte [] image = getResource(resource_name, target);
			return (Toolkit.getDefaultToolkit().createImage(image));
		}
		catch (IOException e) { System.err.println(e); }
		return(null);
*/
		try
		{
			URL url = classloader.getResource(resource_name);
			Image image = ((Applet)obj).getImage(url);
			return(image);
		}
		catch (Exception e)	{}

		System.err.println("Cannot open image file : " + resource_name);
		return(null);
    }

    private static AudioClip createSound(String resource_name)
	{
		try
		{
//			URL url = new URL(((Applet)obj).getCodeBase() + resource_name);
			URL url = classloader.getResource(resource_name);
			AudioClip clip = ((Applet)obj).getAudioClip(url);
			return(clip);
		}
		catch (Exception e)	{}

		System.err.println("Cannot open sound file : " + resource_name);
		return(null);
    }
}
